classdef orTuning <tuning
    
    properties
        units = '';
        calcMethod
        tuningParams
    end
    methods
        function s = orTuning(calcMethod,tuningParams,type)
            if ~exist('type','var')||isempty(type)
                type = 'orTuning';
            end
            s = s@tuning(type);
            if ischar(calcMethod)
                ok = false;
                switch calcMethod
                    case 'vonMises'
                        if all(ismember(fieldnames(tuningParams),{'alpha','thetahat','kappa','DSI'}))...
                                && isnumeric(tuningParams.alpha) && isnumeric(tuningParams.thetahat) && isnumeric(tuningParams.kappa) && isnumeric(tuningParams.DSI)
                            ok = true;
                        end
                end
                if ~ok
                    error('orTuning:inappropriateInput','calcMethod is wrong or params do not match calcMethod');
                end
                s.calcMethod = calcMethod;
                s.tuningParams = tuningParams;
            else
                error('orTuning:wrongType','type needs to be a char');
            end
        end
        
        function out = sample(s,stim)
            switch s.calcMethod
                case 'vonMises'
                    OR = getOrientation(stim);
                    p1 = circ_vmpdf(s.tuningParams.alpha,s.tuningParams.thetahat,s.tuningParams.kappa);
                    p2 = circ_vmpdf(s.tuningParams.alpha,mod(s.tuningParams.thetahat+pi,2*pi),s.tuningParams.kappa);
                    a = (1-s.tuningParams.DSI)/(1+s.tuningParams.DSI);
                    p = (p1+a*p2)/(max(p1+a*p2)); % normalize to 1
                    % find closest alpha
                    if OR<min(s.tuningParams.alpha)
                        out = p(1);
                    elseif OR>max(s.tuningParams.alpha)
                        out = p(end);
                    else
                        out = interp1(s.tuningParams.alpha,p,OR,'cubic');
                    end
            end
        end
        
        function out = getOptOr(s)
            switch s.calcMethod
                case 'vonMises'
                    out = s.tuningParams.thetahat;
            end
        end
    end
end